package com.superai.controller;

import io.github.imfangs.dify.client.DifyChatClient;
import io.github.imfangs.dify.client.callback.ChatStreamCallback;
import io.github.imfangs.dify.client.enums.ResponseMode;
import io.github.imfangs.dify.client.event.*;
import io.github.imfangs.dify.client.model.chat.*;
import io.github.imfangs.dify.client.model.common.SimpleResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 对话型应用控制器
 *
 * 这个控制器提供了与Dify对话型应用交互的API，包括：
 * - 发送对话消息（阻塞模式和流式模式）
 * - 会话管理（获取会话列表、重命名会话、删除会话）
 * - 消息管理（获取历史消息、消息反馈）
 * - 语音转换（语音转文字、文字转语音）
 * - 获取建议问题
 */
@RestController
@RequestMapping("/chat")
@RequiredArgsConstructor
public class ChatController {

    /**
     * Dify聊天客户端，通过构造函数注入
     */
    @Autowired
    private  DifyChatClient chatClient;

    /**
     * 存储SSE连接的映射表，用于流式响应
     */
    private final ConcurrentHashMap<String, SseEmitter> sseEmitters = new ConcurrentHashMap<>();

    /**
     * 发送对话消息（阻塞模式）
     *
     * @param request 聊天消息请求
     * @return 聊天消息响应
     */
    @PostMapping
    public ResponseEntity<ChatMessageResponse> sendChatMessage(@RequestBody ChatMessageRequest request) {
        try {
            // 创建聊天消息
            ChatMessage message = new ChatMessage();
            message.setQuery(request.getQuery());
            message.setUser(request.getUser());
            message.setInputs(request.getInputs());
            // 注意：这里不直接设置files，因为需要的是FileInfo类型
            message.setResponseMode(ResponseMode.BLOCKING);

            // 发送消息并获取响应
            ChatMessageResponse response = chatClient.sendChatMessage(message);
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            // 记录异常并返回错误响应
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 发送对话消息（流式模式）
     *
     * @param request 聊天消息请求
     * @return SSE发射器，用于流式传输响应
     */
    @PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter sendChatMessageStream(@RequestBody ChatMessageRequest request) {
        // 创建SSE发射器，设置超时时间为30分钟
        SseEmitter emitter = new SseEmitter(1800000L);
        String emitterId = request.getUser() + "_" + System.currentTimeMillis();
        sseEmitters.put(emitterId, emitter);

        try {
            // 创建聊天消息
            ChatMessage message = new ChatMessage();
            message.setQuery(request.getQuery());
            message.setUser(request.getUser());
            message.setInputs(request.getInputs());
            // 注意：这里不直接设置files，因为需要的是FileInfo类型
            message.setResponseMode(ResponseMode.STREAMING);

            // 发送流式消息
            chatClient.sendChatMessageStream(message, new ChatStreamCallback() {
                @Override
                public void onMessage(MessageEvent event) {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("message")
                                .data(event));
                    } catch (IOException e) {
                        onException(e);
                    }
                }

                @Override
                public void onMessageEnd(MessageEndEvent event) {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("message_end")
                                .data(event));
                        emitter.complete();
                    } catch (IOException e) {
                        onException(e);
                    } finally {
                        sseEmitters.remove(emitterId);
                    }
                }

                @Override
                public void onMessageFile(MessageFileEvent event) {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("message_file")
                                .data(event));
                    } catch (IOException e) {
                        onException(e);
                    }
                }

                @Override
                public void onTTSMessage(TtsMessageEvent event) {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("tts_message")
                                .data(event));
                    } catch (IOException e) {
                        onException(e);
                    }
                }

                @Override
                public void onTTSMessageEnd(TtsMessageEndEvent event) {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("tts_message_end")
                                .data(event));
                    } catch (IOException e) {
                        onException(e);
                    }
                }

                @Override
                public void onMessageReplace(MessageReplaceEvent event) {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("message_replace")
                                .data(event));
                    } catch (IOException e) {
                        onException(e);
                    }
                }

                @Override
                public void onAgentMessage(AgentMessageEvent event) {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("agent_message")
                                .data(event));
                    } catch (IOException e) {
                        onException(e);
                    }
                }

                @Override
                public void onAgentThought(AgentThoughtEvent event) {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("agent_thought")
                                .data(event));
                    } catch (IOException e) {
                        onException(e);
                    }
                }

                @Override
                public void onError(ErrorEvent event) {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("error")
                                .data(event));
                        emitter.complete();
                    } catch (IOException e) {
                        onException(e);
                    } finally {
                        sseEmitters.remove(emitterId);
                    }
                }

                @Override
                public void onException(Throwable throwable) {
                    emitter.completeWithError(throwable);
                    sseEmitters.remove(emitterId);
                }

                @Override
                public void onPing(PingEvent event) {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("ping")
                                .data(event));
                    } catch (IOException e) {
                        // 忽略心跳事件的异常
                    }
                }
            });
        } catch (IOException e) {
            emitter.completeWithError(e);
            sseEmitters.remove(emitterId);
        }

        // 设置超时和完成回调
        emitter.onTimeout(() -> sseEmitters.remove(emitterId));
        emitter.onCompletion(() -> sseEmitters.remove(emitterId));

        return emitter;
    }

    /**
     * 获取会话列表
     *
     * @param user 用户ID
     * @param lastId 上一页最后一条记录的ID（用于分页）
     * @param limit 每页记录数
     * @param order 排序方式
     * @return 会话列表响应
     */
    @GetMapping("/conversations")
    public ResponseEntity<ConversationListResponse> getConversations(
            @RequestParam String user,
            @RequestParam(required = false) String lastId,
            @RequestParam(defaultValue = "20") Integer limit,
            @RequestParam(defaultValue = "-updated_at") String order) {
        try {
            ConversationListResponse response = chatClient.getConversations(user, lastId, limit, order);
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 获取会话历史消息
     *
     * @param conversationId 会话ID
     * @param user 用户ID
     * @param firstId 第一页第一条记录的ID（用于分页）
     * @param limit 每页记录数
     * @return 消息列表响应
     */
    @GetMapping("/conversations/{conversationId}/messages")
    public ResponseEntity<MessageListResponse> getMessages(
            @PathVariable String conversationId,
            @RequestParam String user,
            @RequestParam(required = false) String firstId,
            @RequestParam(defaultValue = "20") Integer limit) {
        try {
            MessageListResponse response = chatClient.getMessages(conversationId, user, firstId, limit);
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 重命名会话
     *
     * @param conversationId 会话ID
     * @param request 重命名请求
     * @return 更新后的会话信息
     */
    @PutMapping("/conversations/{conversationId}/rename")
    public ResponseEntity<Conversation> renameConversation(
            @PathVariable String conversationId,
            @RequestBody RenameConversationRequest request) {
        try {
            Conversation response = chatClient.renameConversation(
                    conversationId,
                    request.getName(),
                    request.isAutoName(),
                    request.getUser());
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 删除会话
     *
     * @param conversationId 会话ID
     * @param user 用户ID
     * @return 简单响应
     */
    @DeleteMapping("/conversations/{conversationId}")
    public ResponseEntity<SimpleResponse> deleteConversation(
            @PathVariable String conversationId,
            @RequestParam String user) {
        try {
            SimpleResponse response = chatClient.deleteConversation(conversationId, user);
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 消息反馈（点赞/点踩）
     *
     * @param messageId 消息ID
     * @param request 反馈请求
     * @return 简单响应
     */
    @PostMapping("/messages/{messageId}/feedback")
    public ResponseEntity<SimpleResponse> feedbackMessage(
            @PathVariable String messageId,
            @RequestBody FeedbackRequest request) {
        try {
            SimpleResponse response = chatClient.feedbackMessage(
                    messageId,
                    request.getRating(),
                    request.getUser(),
                    request.getComment());
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 获取建议问题
     *
     * @param messageId 消息ID
     * @param user 用户ID
     * @return 建议问题响应
     */
    @GetMapping("/messages/{messageId}/suggested-questions")
    public ResponseEntity<SuggestedQuestionsResponse> getSuggestedQuestions(
            @PathVariable String messageId,
            @RequestParam String user) {
        try {
            SuggestedQuestionsResponse response = chatClient.getSuggestedQuestions(messageId, user);
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 语音转文字
     *
     * @param file 音频文件
     * @param user 用户ID
     * @return 转换后的文本响应
     * @throws IOException 如果文件处理出错
     */
    @PostMapping("/audio-to-text")
    public ResponseEntity<AudioToTextResponse> audioToText(
            @RequestParam("file") MultipartFile file,
            @RequestParam String user) {
        try {
            // 将MultipartFile转换为File
            File tempFile = createTempFileFromMultipartFile(file);
            AudioToTextResponse response = chatClient.audioToText(tempFile, user);
            // 删除临时文件
            tempFile.delete();
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 文字转语音
     *
     * @param request 文字转语音请求
     * @return 音频数据
     */
    @PostMapping(value = "/text-to-audio", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public ResponseEntity<byte[]> textToAudio(@RequestBody TextToAudioRequest request) {
        try {
            byte[] audioData = chatClient.textToAudio(
                    request.getConversationId(),
                    request.getText(),
                    request.getUser());
            return ResponseEntity.ok()
                    .header("Content-Disposition", "attachment; filename=audio.mp3")
                    .body(audioData);
        } catch (IOException e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 获取应用信息
     *
     * @return 应用信息响应
     */
    @GetMapping("/app-info")
    public ResponseEntity<AppInfoResponse> getAppInfo() {
        try {
            AppInfoResponse response = chatClient.getAppInfo();
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 获取应用参数
     *
     * @return 应用参数响应
     */
    @GetMapping("/app-parameters")
    public ResponseEntity<AppParametersResponse> getAppParameters() {
        try {
            AppParametersResponse response = chatClient.getAppParameters();
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 将MultipartFile转换为File
     *
     * @param multipartFile MultipartFile对象
     * @return File对象
     * @throws IOException 如果文件处理出错
     */
    private File createTempFileFromMultipartFile(MultipartFile multipartFile) throws IOException {
        String originalFilename = multipartFile.getOriginalFilename();
        String suffix = originalFilename != null ? originalFilename.substring(originalFilename.lastIndexOf(".")) : ".tmp";
        String prefix = UUID.randomUUID().toString();
        File tempFile = File.createTempFile(prefix, suffix);
        Path path = tempFile.toPath();
        Files.copy(multipartFile.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
        return tempFile;
    }

    /**
     * 聊天消息请求类
     */
    public static class ChatMessageRequest {
        private String query;
        private String user;
        private List<String> files;
        private java.util.Map<String, Object> inputs;

        // Getters and setters
        public String getQuery() {
            return query;
        }

        public void setQuery(String query) {
            this.query = query;
        }

        public String getUser() {
            return user;
        }

        public void setUser(String user) {
            this.user = user;
        }

        public List<String> getFiles() {
            return files;
        }

        public void setFiles(List<String> files) {
            this.files = files;
        }

        public java.util.Map<String, Object> getInputs() {
            return inputs;
        }

        public void setInputs(java.util.Map<String, Object> inputs) {
            this.inputs = inputs;
        }
    }

    /**
     * 重命名会话请求类
     */
    public static class RenameConversationRequest {
        private String name;
        private boolean autoName;
        private String user;

        // Getters and setters
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public boolean isAutoName() {
            return autoName;
        }

        public void setAutoName(boolean autoName) {
            this.autoName = autoName;
        }

        public String getUser() {
            return user;
        }

        public void setUser(String user) {
            this.user = user;
        }
    }

    /**
     * 反馈请求类
     */
    public static class FeedbackRequest {
        private String rating;
        private String user;
        private String comment;

        // Getters and setters
        public String getRating() {
            return rating;
        }

        public void setRating(String rating) {
            this.rating = rating;
        }

        public String getUser() {
            return user;
        }

        public void setUser(String user) {
            this.user = user;
        }

        public String getComment() {
            return comment;
        }

        public void setComment(String comment) {
            this.comment = comment;
        }
    }

    /**
     * 文字转语音请求类
     */
    public static class TextToAudioRequest {
        private String conversationId;
        private String text;
        private String user;

        // Getters and setters
        public String getConversationId() {
            return conversationId;
        }

        public void setConversationId(String conversationId) {
            this.conversationId = conversationId;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

        public String getUser() {
            return user;
        }

        public void setUser(String user) {
            this.user = user;
        }
    }
}
